package com.qp.basics.auth.config;

import com.qp.basics.auth.service.RedisAuthorizationCodeServices;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.provider.client.JdbcClientDetailsService;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;
import org.springframework.security.oauth2.provider.token.store.KeyStoreKeyFactory;

@EnableAuthorizationServer // 开启授权服务器的功能
@Configuration
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Qualifier("userDetailsService")
    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    JdbcClientDetailsService jdbcClientDetailsService;

    @Autowired
    RedisAuthorizationCodeServices redisAuthorizationCodeServices;

    private String path = "yqmicroservices.jks";
    private String pass = "yqmicroservices321@#!";
    private String alias = "yqmicroservices";

    /**
     * 添加第三方的客户端
     */
//    @Override
//    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
//        clients.inMemory()
//            .withClient("yq-sass-api") // 第三方客户端的名称
//            .secret(passwordEncoder.encode("yq-sass-secret")) //  第三方客户端的密钥
//            .scopes("all") //第三方客户端的授权范围
//            .authorizedGrantTypes("password", "refresh_token")
//            .accessTokenValiditySeconds(7 * 24 *3600) // token的有效期
////            .accessTokenValiditySeconds(1 * 3600) // token的有效期，测试。如果token本身过期，redis里面没过期，spring也会认定为过期了
//            .refreshTokenValiditySeconds(30 * 24 * 3600)// refresh_token的有效期
//            .and()
//            .withClient("inner-app")
//            .secret(passwordEncoder.encode("inner-secret"))
//            .authorizedGrantTypes("client_credentials")
//            .scopes("all")
//            .accessTokenValiditySeconds(Integer.MAX_VALUE) ;
//
//        super.configure(clients);
//    }

    /**
     * 配置验证管理器，UserdetailService
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .tokenStore(jwtTokenStore())// tokenStore 来存储我们的token jwt 存储token
                .tokenEnhancer(jwtAccessTokenConverter())
                .authorizationCodeServices(redisAuthorizationCodeServices)
        ;

    }

    private TokenStore jwtTokenStore() {
        JwtTokenStore jwtTokenStore = new JwtTokenStore(jwtAccessTokenConverter());
        return jwtTokenStore;
    }

    public JwtAccessTokenConverter jwtAccessTokenConverter() {
        JwtAccessTokenConverter tokenConverter = new JwtAccessTokenConverter();

        // 加载我们的私钥
        ClassPathResource classPathResource = new ClassPathResource(path);
        KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(classPathResource, pass.toCharArray());
        tokenConverter.setKeyPair(keyStoreKeyFactory.getKeyPair(alias, pass.toCharArray()));
        return tokenConverter;
    }


    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService);
    }
}
